package com.gitee.minimalismstyle.fresh.common.document.service.impl

import com.fasterxml.jackson.databind.ObjectMapper
import com.gitee.minimalismstyle.fresh.common.api.OssApi
import com.gitee.minimalismstyle.fresh.common.core.config.FreshProperties
import com.gitee.minimalismstyle.fresh.common.core.domain.R
import com.gitee.minimalismstyle.fresh.common.core.domain.SnowflakeIdWorker
import com.gitee.minimalismstyle.fresh.common.core.extra.write
import com.gitee.minimalismstyle.fresh.common.core.spring.SpringContextUtils
import com.gitee.minimalismstyle.fresh.common.document.domain.ImportStatus
import com.gitee.minimalismstyle.fresh.common.document.execl.ExeclResolver
import com.gitee.minimalismstyle.fresh.common.document.handler.ExeclImportHandler
import com.gitee.minimalismstyle.fresh.common.document.service.ImportService
import com.gitee.minimalismstyle.fresh.common.document.service.WorkbookService
import com.gitee.minimalismstyle.fresh.common.web.extra.toMultipartFile
import org.apache.commons.io.FileUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.io.FileOutputStream

@Service
class ImportServiceImpl(val workbookService: WorkbookService,
                        val redisTemplate: StringRedisTemplate,
                        val freshProperties: FreshProperties,
                        val snowflakeIdWorker: SnowflakeIdWorker,
                        val objectMapper: ObjectMapper
    ): ImportService {
    @Autowired
    private lateinit var ossApi: OssApi

    override fun save(file: MultipartFile): ImportStatus {
        val  result = ossApi.upload(file).get(mapOf())
        val importStatus = ImportStatus()
        importStatus.id = snowflakeIdWorker.nextId()
        importStatus.fileId = result["id"] as Long
        importStatus.status = 0
        val jsonString = objectMapper.writeValueAsString(importStatus)
        redisTemplate.opsForValue().set("IMPORT_${importStatus.id}", jsonString)
        return importStatus
    }

    override fun import(id: String, fileId: Long, params: Map<String, Any>) {
        var jsonString = redisTemplate.opsForValue().get("IMPORT_$id")
        val importStatus = objectMapper.readValue(jsonString, ImportStatus::class.java)
        val tempdir = freshProperties.tempdir.replaceFirst("classes:", this.javaClass.getResource("/").path)
        val response = ossApi.getResponse(importStatus.fileId!!)
        val tempPath = "$tempdir/import/$fileId.xlsx"
        FileOutputStream(tempPath).use{
            response.body().asInputStream().write(it, response.body().length())
        }

        val workbook = workbookService.findById(id)
        val file = File(tempPath)
        val workbookData = ExeclResolver.read(workbook, file)
        workbookData.putAll(params)

        if(workbook.handler != null){
            val execlImportHandler: ExeclImportHandler = SpringContextUtils.getBean(workbook.handler!!)
            val handlerR = execlImportHandler.validate(workbookData)
            if(workbookData.isAllValid()){
                if(handlerR.success){
                    execlImportHandler.finish(workbookData)
                }else{
                    val result = ossApi.upload(file.toMultipartFile()).get(mapOf())
                    importStatus.errorFileId = result["id"] as Long
                    importStatus.success = false
                }
            }
            importStatus.status = 10
        }
        ossApi.deleteById(importStatus.fileId!!)
        FileUtils.deleteDirectory(file)
        jsonString = objectMapper.writeValueAsString(importStatus)
        redisTemplate.opsForValue().set("IMPORT_${importStatus.id}", jsonString)
    }

    override fun findStatus(id: Long): R<ImportStatus> {
        val jsonString = redisTemplate.opsForValue().get("IMPORT_$id")
        return R.success(objectMapper.readValue(jsonString, ImportStatus::class.java))
    }
}